Multi-Page React Application
A Multi-Page React Application allows users to navigate between different pages, such as Home, About, Services, Products, Contact, Login, and Dashboard. React applications commonly use client-side routing to display different page components based on the URL without reloading the entire document. React Router is a popular library for implementing navigation and routing in React applications.
React JS Course: JustAcademy React JS Training Course
Course Demo: Register for React JS Course Demo
1. Learning Objectives
- Understand multi-page navigation in React.
- Learn the difference between traditional multi-page websites and React single-page applications with multiple routes.
- Install and configure React Router.
- Create separate page components.
- Navigate using Link and NavLink.
- Define routes using Routes and Route.
- Understand dynamic route parameters.
- Implement nested routes and shared layouts.
- Create a custom 404 Not Found page.
- Understand protected routes and authentication concepts.
- Build and test a complete multi-page React application.
2. What Is a Multi-Page React Application?
A Multi-Page React Application is a React website that contains multiple navigable views, each associated with a URL. For example, a user can visit / for Home, /about for About, and /contact for Contact.
With client-side routing, React can render the appropriate page component while keeping the application running in the browser. The application can therefore provide multiple URLs without requiring a full document reload for every internal navigation.
Examples of Pages
- Home Page: Introduces the website.
- About Page: Provides information about the company.
- Services Page: Displays available services.
- Products Page: Lists products.
- Contact Page: Displays contact information or a form.
- Login Page: Allows users to sign in.
- Dashboard Page: Displays personalized information.
3. Traditional Multi-Page Website vs React Routing
| Feature |
Traditional Multi-Page Website |
React Client-Side Routing |
| Navigation |
Usually requests a new HTML document. |
Usually updates the displayed React view. |
| Page rendering |
Often handled by the server. |
Routes commonly render components in the browser. |
| URL changes |
Yes |
Yes |
| Full document reload |
Usually occurs during navigation. |
Usually avoided during internal navigation. |
| Routing |
Often managed by server routes. |
Can be managed by React Router. |
| Best suited for |
Traditional server-rendered websites. |
Interactive React applications. |
Important: A React application can have multiple pages or routes while still being a Single Page Application (SPA). The number of routes does not determine whether the browser loads a new HTML document on each navigation.
4. Technologies Used
| Technology |
Purpose |
| React JS |
Builds the user interface using components. |
| JavaScript |
Implements application logic. |
| JSX |
Defines component UI. |
| React Router |
Maps URLs to React page components. |
| BrowserRouter |
Enables browser-based client-side routing in declarative routing setups. |
| Routes and Route |
Define which component appears for a matching URL. |
| Link |
Navigates between routes without a full document reload. |
| NavLink |
Creates navigation links with active-route styling support. |
| useParams |
Reads dynamic route parameters. |
| Outlet |
Renders matching child routes inside a parent layout. |
5. Create a React Project
Make sure Node.js and npm are installed. Create a React project using Vite.
npm create vite@latest multi-page-react-app -- --template react
cd multi-page-react-app
npm install
npm install react-router-dom
npm run dev
Open the development URL shown in your terminal. This example uses the familiar declarative routing API from React Router DOM.
Recommended Folder Structure
multi-page-react-app/
├── src/
│ ├── components/
│ │ └── Navbar.jsx
│ ├── pages/
│ │ ├── Home.jsx
│ │ ├── About.jsx
│ │ ├── Services.jsx
│ │ ├── Contact.jsx
│ │ ├── ProductDetails.jsx
│ │ └── NotFound.jsx
│ ├── App.jsx
│ ├── App.css
│ ├── index.css
│ └── main.jsx
├── package.json
└── index.html
6. Create Individual Page Components
Each page should be created as a separate React component. This makes the application organized, reusable, and easier to maintain.
6.1 Home.jsx
function Home() {
return (
<section className="page">
<h1>Welcome to Our Website</h1>
<p>Explore our services and learn more about our company.</p>
</section>
);
}
export default Home;
6.2 About.jsx
function About() {
return (
<section className="page">
<h1>About Us</h1>
<p>We build modern websites and digital experiences.</p>
</section>
);
}
export default About;
6.3 Services.jsx
function Services() {
const services = [
"Web Development",
"UI/UX Design",
"React Application Development"
];
return (
<section className="page">
<h1>Our Services</h1>
<ul>
{services.map((service) => (
<li key={service}>{service}</li>
))}
</ul>
</section>
);
}
export default Services;
6.4 Contact.jsx
function Contact() {
return (
<section className="page">
<h1>Contact Us</h1>
<p>Email: [email protected]</p>
<p>Phone: +91 98765 43210</p>
</section>
);
}
export default Contact;
7. Create the Navbar Component
The navigation bar provides links to the different pages. React Router's Link component allows navigation without a full browser document reload.
Create src/components/Navbar.jsx:
import { NavLink } from "react-router-dom";
function Navbar() {
return (
<header className="navbar">
<div className="logo">MyWebsite</div>
<nav aria-label="Main navigation">
<NavLink to="/" end>Home</NavLink>
<NavLink to="/about">About</NavLink>
<NavLink to="/services">Services</NavLink>
<NavLink to="/contact">Contact</NavLink>
</nav>
</header>
);
}
export default Navbar;
Explanation
NavLink navigates to a route and supports active-link styling.
to specifies the destination URL.
end on the Home link ensures it is active only for the exact root route.
- The navigation bar can be reused across all pages.
8. Configure React Router in App.jsx
The Routes component contains Route definitions. Each Route connects a URL path with a React component.
Create src/App.jsx:
import {
BrowserRouter,
Routes,
Route
} from "react-router-dom";
import Navbar from "./components/Navbar";
import Home from "./pages/Home";
import About from "./pages/About";
import Services from "./pages/Services";
import Contact from "./pages/Contact";
import NotFound from "./pages/NotFound";
import "./App.css";
function App() {
return (
<BrowserRouter>
<Navbar />
<main>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/services" element={<Services />} />
<Route path="/contact" element={<Contact />} />
<Route path="*" element={<NotFound />} />
</Routes>
</main>
</BrowserRouter>
);
}
export default App;
How It Works
BrowserRouter provides browser-based routing context.
Routes selects the route that matches the current URL.
Route defines the path and corresponding component.
element specifies the React element rendered for the route.
- The wildcard path
* handles unmatched URLs.
9. Create a 404 Not Found Page
A 404 page appears when a user visits a URL that does not match any defined route.
Create src/pages/NotFound.jsx:
import { Link } from "react-router-dom";
function NotFound() {
return (
<section className="page not-found">
<h1>404 - Page Not Found</h1>
<p>Sorry, the page you are looking for does not exist.</p>
<Link to="/">Return to Home</Link>
</section>
);
}
export default NotFound;
10. Link vs NavLink vs Anchor Tag
| Feature |
Link |
NavLink |
Anchor Tag |
| Purpose |
Internal route navigation. |
Internal navigation with active-route support. |
Standard browser navigation. |
| Full page reload |
Normally avoided for internal routes. |
Normally avoided for internal routes. |
Usually occurs when navigating to another document. |
| Active route styling |
Not built in. |
Supported. |
Not built in. |
| Typical use |
Buttons or text links between app pages. |
Navigation menus. |
External websites or regular document links. |
Use React Router's Link or NavLink for internal routes. Use a regular anchor for external destinations, downloads, and navigation that should follow standard browser behavior.
11. Dynamic Routes and URL Parameters
Dynamic routes allow one component to display different content based on a URL parameter. For example, /products/101 and /products/102 can use the same product details component.
Define a Dynamic Route
<Route path="/products/:productId" element={<ProductDetails />} />
Create ProductDetails.jsx
import { useParams, Link } from "react-router-dom";
const products = {
"101": { name: "Laptop", price: 65000 },
"102": { name: "Headphones", price: 2500 },
"103": { name: "Smart Watch", price: 4500 }
};
function ProductDetails() {
const { productId } = useParams();
const product = products[productId];
if (!product) {
return (
<section className="page">
<h1>Product Not Found</h1>
<Link to="/products">View Products</Link>
</section>
);
}
return (
<section className="page">
<h1>{product.name}</h1>
<p>Price: ₹{product.price.toLocaleString("en-IN")}</p>
<p>Product ID: {productId}</p>
</section>
);
}
export default ProductDetails;
Add the route to the Routes list:
<Route path="/products/:productId" element={<ProductDetails />} />
Important: This example uses local sample data. In a real application, product details are commonly fetched from an API or database-backed service.
12. Nested Routes and Shared Layouts
Nested routes allow several pages to share a common layout. For example, a dashboard can have a common sidebar and separate Overview, Profile, and Settings pages.
Example Dashboard Layout
import { NavLink, Outlet } from "react-router-dom";
function DashboardLayout() {
return (
<div className="dashboard-layout">
<aside className="dashboard-sidebar">
<h2>Dashboard</h2>
<NavLink to="/dashboard" end>Overview</NavLink>
<NavLink to="/dashboard/profile">Profile</NavLink>
<NavLink to="/dashboard/settings">Settings</NavLink>
</aside>
<section className="dashboard-content">
<Outlet />
</section>
</div>
);
}
export default DashboardLayout;
Configure Nested Routes
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} />
<Route path="profile" element={<Profile />} />
<Route path="settings" element={<Settings />} />
</Route>
The Outlet component renders the matching child route inside the shared layout. The index route renders at /dashboard, while the other child routes render at /dashboard/profile and /dashboard/settings.
13. Protected Routes and Authentication
Protected routes restrict access to pages that require a signed-in user, such as a dashboard or account page. A simple client-side guard can improve navigation, but it is not a substitute for server-side security.
Example Protected Route
import { Navigate, Outlet, useLocation } from "react-router-dom";
function ProtectedRoute({ isAuthenticated }) {
const location = useLocation();
if (!isAuthenticated) {
return (
<Navigate
to="/login"
replace
state={{ from: location }}
/>
);
}
return <Outlet />;
}
export default ProtectedRoute;
Route Configuration
<Route element={<ProtectedRoute isAuthenticated={isAuthenticated} />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/account" element={<Account />} />
</Route>
In this example, isAuthenticated represents the application's authentication state. A real application should obtain and validate that state using a suitable authentication system. The backend must independently verify user identity and permissions for protected data and operations.
14. Query Parameters
Query parameters store optional information in the URL. For example, /products?category=electronics can represent a product category filter.
import { useSearchParams } from "react-router-dom";
function ProductFilter() {
const [searchParams, setSearchParams] = useSearchParams();
const category = searchParams.get("category") || "all";
function showElectronics() {
setSearchParams({ category: "electronics" });
}
function showAll() {
setSearchParams({});
}
return (
<section className="page">
<p>Selected category: {category}</p>
<button onClick={showElectronics}>Electronics</button>
<button onClick={showAll}>Show All</button>
</section>
);
}
export default ProductFilter;
15. Add CSS Styling
Create src/App.css to style the navigation bar and pages.
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
gap: 20px;
padding: 18px 32px;
background: #172554;
color: #ffffff;
}
.logo {
font-size: 22px;
font-weight: bold;
}
.navbar nav {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.navbar nav a {
padding: 10px 12px;
border-radius: 6px;
color: #dbeafe;
text-decoration: none;
}
.navbar nav a:hover,
.navbar nav a.active {
background: #2563eb;
color: #ffffff;
}
.page {
max-width: 1100px;
margin: 0 auto;
padding: 40px 24px;
}
.page h1 {
margin-top: 0;
color: #172554;
}
.page p,
.page li {
line-height: 1.7;
}
.page a {
color: #1d4ed8;
}
.not-found {
text-align: center;
}
.dashboard-layout {
display: flex;
min-height: 70vh;
}
.dashboard-sidebar {
display: flex;
flex-direction: column;
gap: 12px;
width: 220px;
padding: 24px;
background: #eff6ff;
}
.dashboard-sidebar a {
padding: 10px;
border-radius: 6px;
text-decoration: none;
}
.dashboard-sidebar a.active {
background: #dbeafe;
font-weight: bold;
}
.dashboard-content {
flex: 1;
min-width: 0;
padding: 24px;
}
@media (max-width: 650px) {
.navbar {
align-items: flex-start;
flex-direction: column;
padding: 16px;
}
.navbar nav {
width: 100%;
}
.page {
padding: 24px 16px;
}
.dashboard-layout {
flex-direction: column;
}
.dashboard-sidebar {
width: 100%;
}
}
16. Global CSS
Create src/index.css:
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial, sans-serif;
color: #1f2937;
background: #f8fafc;
}
button,
input,
select,
textarea {
font: inherit;
}
a:focus-visible,
button:focus-visible,
input:focus-visible {
outline: 3px solid #60a5fa;
outline-offset: 2px;
}
17. Main Entry Point
Vite's default src/main.jsx can render the App component as follows:
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import "./index.css";
createRoot(document.getElementById("root")).render(
<StrictMode>
<App />
</StrictMode>
);
18. How Routing Works
- The user opens a URL or clicks a navigation link.
- React Router reads the current location.
- The router finds the matching route configuration.
- The corresponding React component is rendered.
- The browser URL updates during navigation.
- Shared layout components remain in place when the route structure allows it.
Example: Clicking About navigates to /about, where the About component is rendered. Clicking Contact navigates to /contact, where the Contact component is rendered.
19. Common Errors and Solutions
| Error |
Possible Solution |
| Cannot find module react-router-dom |
Run npm install react-router-dom and restart the development server if necessary. |
| Page does not change |
Verify the route path and the destination in Link or NavLink. |
| Router context error |
Ensure routing components are rendered within the correct router provider. |
| 404 on refreshing a nested URL |
Configure the hosting server to serve the SPA entry document for client-side routes. |
| Dynamic page shows no data |
Check the parameter name and verify the matching record exists. |
| Nested page does not appear |
Ensure the parent layout includes Outlet. |
| Active navigation style is missing |
Use NavLink and check the active CSS selector. |
| Protected page is exposed |
Enforce authentication and authorization on the server, not only in React. |
20. Best Practices
- Keep each major page in a separate component file.
- Use descriptive route paths such as
/services and /products/:productId.
- Use Link and NavLink for internal navigation.
- Use nested routes for shared layouts.
- Display a useful Not Found page.
- Validate dynamic parameters and handle missing records.
- Use loading and error states when retrieving data.
- Keep authentication state and route logic organized.
- Protect sensitive data and API operations on the backend.
- Test direct URL access, page refreshes, and mobile navigation.
- Configure hosting rewrites for client-side routes where required.
- Consider route-level code splitting for large applications.
21. Testing Checklist
- Verify that Home, About, Services, and Contact open correctly.
- Confirm that internal navigation does not cause unnecessary full-page reloads.
- Test active navigation styling.
- Visit an invalid URL and verify the 404 page.
- Open a valid dynamic product URL.
- Open a product URL with an unknown ID.
- Verify nested dashboard routes render inside the shared layout.
- Test query parameter changes.
- Test protected routes when signed in and signed out.
- Refresh a nested URL on the deployed application.
- Check keyboard navigation and responsive layouts.
22. Interview Questions and Answers
Q1. What is a Multi-Page React Application?
It is a React application with multiple navigable views, commonly mapped to different URLs using a routing library.
Q2. What is React Router?
React Router is a routing library that maps URLs to components and supports navigation, nested routes, route parameters, and other routing features.
Q3. What is BrowserRouter?
BrowserRouter provides browser-history-based routing context for a declarative React Router application.
Q4. What is the purpose of Routes and Route?
Routes selects the matching route, while Route defines the URL pattern and the element to render.
Q5. What is the difference between Link and NavLink?
Both provide internal navigation. NavLink also supports active-route styling and related state.
Q6. What are dynamic routes?
Dynamic routes contain parameters, such as /products/:productId, that can vary between URLs.
Q7. What does useParams do?
useParams reads the parameters matched by the current route.
Q8. What is a nested route?
A nested route is defined inside a parent route and can render within the parent's layout using Outlet.
Q9. What is a 404 page?
A 404 page informs users that the requested route does not exist in the application.
Q10. How do protected routes work?
A route guard checks application authentication state and redirects users who are not allowed to view a page. The backend must still enforce access control.
Q11. Does a React application with multiple routes require a full page reload for every navigation?
No. Client-side routing can change the displayed component and URL without reloading the entire document.
Q12. Why can a deployed route fail when refreshed?
The hosting server may not be configured to serve the application's entry document for client-side paths. A suitable fallback or rewrite configuration may be required.
23. Practical Exercises
- Create Home, About, Services, and Contact pages.
- Add a responsive navigation bar using NavLink.
- Create a Products page with links to individual product details.
- Use useParams to read a product ID from the URL.
- Create a custom 404 page.
- Build a nested Dashboard layout with Profile and Settings routes.
- Add search or category filters using query parameters.
- Create a login page and demonstrate a protected route with sample authentication state.
- Load page data from an API and handle loading and error states.
- Deploy the application and test direct route access and page refreshes.
24. Quick Revision
- React Router: Manages navigation and route matching.
- BrowserRouter: Enables browser-based routing.
- Routes: Selects the matching route.
- Route: Connects a path to a component.
- Link: Navigates between internal routes.
- NavLink: Supports active navigation styling.
- useParams: Reads dynamic route parameters.
- useSearchParams: Reads and updates query parameters.
- Outlet: Renders matching child routes.
- Navigate: Redirects to another route.
- 404 Route: Handles unmatched paths.
- Protected Route: Controls client-side access based on authentication state.
25. Official Documentation and Learning Resources
26. React JS Course and Demo Links
Explore the React JS training course and register for a course demonstration using these links:
Conclusion
A Multi-Page React Application helps developers build organized websites with multiple URLs and reusable page components. By learning React Router, Link, NavLink, dynamic routes, nested layouts, query parameters, and protected routes, developers can build scalable applications such as e-commerce websites, admin panels, portfolios, and business platforms. Practice the examples and extend them with API integration, authentication, responsive design, and testing.